#include "networkmanager.h"
#include "websocketserver.h"
#include <QDebug>
#include <QBuffer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QImage>
#include <QTimer>
#include <iostream>
#include <boost/beast.hpp>
#include <boost/asio.hpp>

namespace beast = boost::beast;
namespace http = beast::http;
namespace websocket = beast::websocket;
namespace asio = boost::asio;
using tcp = boost::asio::ip::tcp;

// WebSocket客户端类：处理客户端连接
class WebSocketClient : public std::enable_shared_from_this<WebSocketClient>
{
public:
    // 构造函数：接收IO上下文和网络管理器
    WebSocketClient(asio::io_context &ioc, NetworkManager *manager)
        : resolver_(ioc), ws_(ioc), manager_(manager), connected_(false), sending_(false) {}

    // 连接到服务器
    void connect(const std::string &host, const std::string &port)
    {
        host_ = host;
        port_ = port;
        // 异步解析域名
        resolver_.async_resolve(host, port,
                                [self = shared_from_this()](beast::error_code ec, tcp::resolver::results_type results)
                                {
                                    if (ec)
                                    {
                                        self->onError(ec, "resolve"); // 解析错误
                                        return;
                                    }
                                    self->onResolve(results); // 解析成功
                                });
    }

    // 发送消息
    void send(const std::string &message, bool is_binary)
    {
        if (!connected_.load()) // 未连接则不发送
            return;

        {
            std::lock_guard<std::mutex> lock(sendMutex_); // 加锁保护发送队列
            sendQueue_.push({message, is_binary});        // 添加到队列
        }

        if (!sending_.load()) // 如果不在发送中，则开始发送
        {
            doWrite();
        }
    }

    // 关闭连接
    void close()
    {
        if (connected_.exchange(false)) // 原子操作设置关闭状态
        {
            beast::error_code ec;
            // 异步关闭WebSocket
            ws_.async_close(websocket::close_code::normal,
                            [self = shared_from_this()](beast::error_code ec)
                            {
                                beast::error_code ignored_ec;
                                // 关闭底层socket
                                self->ws_.next_layer().shutdown(tcp::socket::shutdown_both, ignored_ec);
                                self->ws_.next_layer().close(ignored_ec);
                            });
        }
    }

    // 检查是否已连接
    bool isConnected() const { return connected_.load(); }

private:
    // 解析成功处理
    void onResolve(tcp::resolver::results_type results)
    {
        // 异步连接到服务器
        asio::async_connect(ws_.next_layer(), results.begin(), results.end(),
                            [self = shared_from_this()](beast::error_code ec, tcp::resolver::iterator)
                            {
                                if (ec)
                                {
                                    self->onError(ec, "connect"); // 连接错误
                                    return;
                                }
                                self->onConnect(); // 连接成功
                            });
    }

    // 连接成功处理
    void onConnect()
    {
        // 设置WebSocket请求头
        ws_.set_option(websocket::stream_base::decorator(
            [](websocket::request_type &req)
            {
                req.set(http::field::user_agent, "VideoChat-Client");
                req.set(http::field::host, "localhost");
            }));

        // 设置超时
        ws_.set_option(websocket::stream_base::timeout::suggested(beast::role_type::client));

        // 异步进行WebSocket握手
        ws_.async_handshake(host_, "/",
                            [self = shared_from_this()](beast::error_code ec)
                            {
                                if (ec)
                                {
                                    self->onError(ec, "ws_handshake"); // 握手错误
                                    return;
                                }
                                self->onHandshake(); // 握手成功
                            });
    }

    // 握手成功处理
    void onHandshake()
    {
        connected_.store(true); // 设置连接状态
        // 通知网络管理器连接成功（使用QueuedConnection确保线程安全）
        QMetaObject::invokeMethod(manager_, [this]()
                                  { manager_->setConnectionStatus(true); }, Qt::QueuedConnection);
        doRead(); // 开始读取消息
    }

    // 开始异步读取消息
    void doRead()
    {
        ws_.async_read(buffer_,
                       [self = shared_from_this()](beast::error_code ec, std::size_t bytes_transferred)
                       {
                           if (ec)
                           {
                               self->onError(ec, "read"); // 读取错误
                               return;
                           }
                           self->onRead(bytes_transferred); // 读取成功
                       });
    }

    // 读取成功处理
    void onRead(std::size_t bytes_transferred)
    {
        bool is_binary = ws_.got_binary();                              // 判断消息类型
        std::string message = beast::buffers_to_string(buffer_.data()); // 转换消息内容
        buffer_.consume(bytes_transferred);                             // 清理缓冲区

        // 通知网络管理器处理消息
        QMetaObject::invokeMethod(manager_, [this, message, is_binary]()
                                  { manager_->processMessage(message, is_binary); }, Qt::QueuedConnection);

        doRead(); // 继续读取下一条消息
    }

    // 处理发送队列
    void doWrite()
    {
        if (!connected_.load()) // 未连接则停止发送
            return;

        std::lock_guard<std::mutex> lock(sendMutex_); // 加锁保护发送队列
        if (sendQueue_.empty())                       // 队列为空则停止发送
        {
            sending_.store(false);
            return;
        }

        sending_.store(true);           // 设置发送状态
        auto item = sendQueue_.front(); // 获取队列首元素
        sendQueue_.pop();

        ws_.binary(item.is_binary); // 设置消息类型

        // 异步发送消息
        ws_.async_write(asio::buffer(item.message),
                        [self = shared_from_this()](beast::error_code ec, std::size_t)
                        {
                            if (ec)
                            {
                                self->onError(ec, "write"); // 发送错误
                                return;
                            }

                            std::lock_guard<std::mutex> lock(self->sendMutex_);
                            if (!self->sendQueue_.empty()) // 队列非空则继续发送
                            {
                                self->doWrite();
                            }
                            else // 队列为空则停止发送
                            {
                                self->sending_.store(false);
                            }
                        });
    }

    // 错误处理
    void onError(beast::error_code ec, const std::string &what)
    {
        // 忽略正常关闭相关错误
        if (ec == websocket::error::closed ||
            ec == asio::error::operation_aborted ||
            ec == asio::error::eof)
        {
            close();
            return;
        }

        // 报告错误
        std::string error = "WebSocket " + what + " error: " + ec.message();
        QMetaObject::invokeMethod(manager_, [this, error]()
                                  { manager_->reportError(QString::fromStdString(error)); }, Qt::QueuedConnection);

        close(); // 出错后关闭连接
    }

    tcp::resolver resolver_;             // 域名解析器
    websocket::stream<tcp::socket> ws_;  // WebSocket流
    beast::flat_buffer buffer_;          // 接收缓冲区
    std::string host_;                   // 服务器主机名
    std::string port_;                   // 服务器端口
    NetworkManager *manager_;            // 网络管理器指针
    std::atomic<bool> connected_{false}; // 连接状态
    std::atomic<bool> sending_{false};   // 发送状态

    std::mutex sendMutex_; // 发送队列互斥锁
    struct SendItem        // 发送队列项
    {
        std::string message;
        bool is_binary;
    };
    std::queue<SendItem> sendQueue_; // 发送队列
};

// 网络管理器构造函数
NetworkManager::NetworkManager(QObject *parent) : QObject(parent)
{
}

// 网络管理器析构函数：停止连接
NetworkManager::~NetworkManager()
{
    stopConnection();
}

// 启动服务器模式
bool NetworkManager::startServer(quint16 port)
{
    if (m_running.load()) // 已运行则先停止
        stopConnection();

    try
    {
        m_server = std::make_unique<WebSocketServer>(); // 创建WebSocket服务器
        // 连接服务器信号
        connect(m_server.get(), &WebSocketServer::messageReceived,
                this, &NetworkManager::onServerMessage);
        connect(m_server.get(), &WebSocketServer::binaryMessageReceived, // 二进制消息
                this, &NetworkManager::onServerBinaryMessage);
        connect(m_server.get(), &WebSocketServer::clientConnected,
                this, &NetworkManager::onClientConnected);
        connect(m_server.get(), &WebSocketServer::clientDisconnected,
                this, &NetworkManager::onClientDisconnected);

        if (m_server->start(port)) // 启动服务器
        {
            m_connectionType = ConnectionType::Server; // 设置连接类型
            setConnectionStatus(true);                 // 设置连接状态
            m_running.store(true);                     // 设置运行状态

            // 服务端开始视频流处理
            startVideoStream();
            return true;
        }
    }
    catch (const std::exception &e) // 捕获异常
    {
        reportError(QString("Server error: %1").arg(e.what()));
    }
    return false;
}

// 处理服务器收到的二进制消息
void NetworkManager::onServerBinaryMessage(const QByteArray &data)
{
    // 检查是否有标识符，并且第一个字节为'V'
    if (data.size() > 0 && data[0] == 'V')
    {
        QImage frame;
        if (frame.loadFromData(data.mid(1), "JPEG")) // 去掉第一个字节再加载
        {
            emit videoFrameReceived(frame);
        }
    }
}

// 启动客户端模式
bool NetworkManager::startClient(const QString &host, quint16 port)
{
    if (m_running.load()) // 已运行则先停止
        stopConnection();

    m_running.store(true);                     // 设置运行状态
    m_connectionType = ConnectionType::Client; // 设置连接类型

    // 启动网络线程
    m_networkThread = std::thread([this, host, port]()
                                  {
                                      try {
                                          asio::io_context ioc;  // 创建IO上下文

                                          m_client = std::make_shared<WebSocketClient>(ioc, this);  // 创建客户端
                                          m_client->connect(host.toStdString(), std::to_string(port));  // 连接服务器

                                          ioc.run();  // 运行IO服务
                                      } catch (const std::exception &e) {  // 捕获异常
                                          reportError(QString("Client error: %1").arg(e.what()));
                                      } });

    return true;
}

// 停止连接
void NetworkManager::stopConnection()
{
    m_running.store(false); // 设置停止状态

    if (m_server) // 停止服务器
    {
        m_server->stop();
        m_server.reset();
    }

    if (m_client) // 停止客户端
    {
        m_client->close();
        m_client.reset();
    }

    // 等待网络线程结束
    if (m_networkThread.joinable())
    {
        m_networkThread.join();
    }

    setConnectionStatus(false); // 设置连接状态
}

// 发送文本消息
void NetworkManager::sendMessage(const QString &message)
{
    if (!m_connected.load()) // 未连接则不发送
        return;

    // 构建JSON消息
    QJsonObject json;
    json["type"] = "message";
    json["content"] = message;
    json["username"] = m_username; // 用户名

    QJsonDocument doc(json);
    std::string data = doc.toJson(QJsonDocument::Compact).toStdString();

    // 根据连接类型发送消息
    if (m_connectionType == ConnectionType::Server && m_server)
    {
        // 服务器广播文本消息给所有客户端
        m_server->broadcast(data, false);
    }
    else if (m_connectionType == ConnectionType::Client && m_client && m_client->isConnected())
    {
        m_client->send(data, false); // 客户端直接发送
    }
}

// 发送视频帧
void NetworkManager::sendVideoFrame(const QImage &frame)
{
    if (!m_connected.load() || !m_videoStreaming.load()) // 未连接或未启用视频流则不发送
        return;

    // 添加帧率控制
    static auto lastSendTime = std::chrono::steady_clock::now();
    auto now = std::chrono::steady_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastSendTime).count();

    // 限制每秒最多15帧（约66ms/帧）
    if (elapsed < 66)
        return;
    lastSendTime = now;

    // 调整图像大小以减少数据量
    QImage scaledFrame = frame.scaled(640, 480, Qt::KeepAspectRatio, Qt::SmoothTransformation);

    QByteArray byteArray;
    QBuffer buffer(&byteArray);
    buffer.open(QIODevice::WriteOnly);

    // 降低JPEG质量以减少数据量（质量50）
    if (scaledFrame.save(&buffer, "JPEG", 50))
    {
        // 统一格式：添加消息类型标识符
        QByteArray messageWithHeader;
        messageWithHeader.append('V'); // 视频帧标识（'V'表示视频）
        messageWithHeader.append(byteArray);

        // 根据连接类型发送
        if (m_connectionType == ConnectionType::Server && m_server)
        {
            m_server->broadcast(messageWithHeader.toStdString(), true);
        }
        else if (m_connectionType == ConnectionType::Client && m_client && m_client->isConnected())
        {
            // 客户端发送带标识符的数据
            std::string dataWithHeader = "V" + byteArray.toStdString();
            m_client->send(dataWithHeader, true);
        }
    }
}

// 开始视频流传输
void NetworkManager::startVideoStream()
{
    m_videoStreaming.store(true);
}

// 停止视频流传输
void NetworkManager::stopVideoStream()
{
    m_videoStreaming.store(false);
    std::lock_guard<std::mutex> lock(m_videoMutex); // 加锁保护队列
    // 清空视频帧队列
    while (!m_videoFrameQueue.empty())
    {
        m_videoFrameQueue.pop();
    }
}

// 设置连接状态并通知
void NetworkManager::setConnectionStatus(bool connected)
{
    if (m_connected.load() != connected) // 状态变化时才处理
    {
        m_connected.store(connected);
        emit connectionStatusChanged(connected); // 发射状态变化信号

        if (!connected) // 断开连接时停止视频流
        {
            stopVideoStream();
        }
    }
}

// 处理接收到的消息
void NetworkManager::processMessage(const std::string &message, bool is_binary)
{
    if (is_binary) // 二进制消息（视频帧）
    {
        QByteArray data(message.data(), message.size());

        // 检查消息类型标识
        if (data.size() > 0 && data[0] == 'V')
        {
            // 去掉第一个字节（消息类型标识）
            QImage frame;
            if (frame.loadFromData(data.mid(1), "JPEG"))
            {                                   // 加载JPEG图像
                emit videoFrameReceived(frame); // 发射视频帧接收信号
            }
        }
    }
    else // 文本消息（JSON格式）
    {
        QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(message));
        if (doc.isNull()) // JSON解析失败
        {
            emit messageReceived(QString::fromStdString(message));
            return;
        }

        QJsonObject json = doc.object();
        QString type = json["type"].toString();

        if (type == "message") // 普通消息
        {
            QString content = json["content"].toString();
            QString sender = json["username"].toString();

            // 格式化消息：用户名: 内容
            QString formattedMessage = sender + ": " + content;
            emit messageReceived(formattedMessage);
            // emit messageReceived(json["content"].toString());
        }
    }
}

// 报告错误
void NetworkManager::reportError(const QString &error)
{
    qDebug() << "Network error:" << error;
    emit errorOccurred(error);  // 发射错误信号
    setConnectionStatus(false); // 设置连接状态为断开
}

// 处理服务器文本消息
void NetworkManager::onServerMessage(const QString &message)
{
    processMessage(message.toStdString(), false); // 服务器消息总是文本
}

// 客户端连接处理
void NetworkManager::onClientConnected()
{
    qDebug() << "Client connected to server";
}

// 客户端断开处理
void NetworkManager::onClientDisconnected()
{
    qDebug() << "Client disconnected from server";
    setConnectionStatus(false); // 设置连接状态为断开
}
